﻿using System;
using System.Linq;
using System.Windows.Forms;

namespace ModbusRTULib
{
    public class Utils
    {
        /// <summary>
        /// 生成crc16校验码
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static byte[] CalculateCRC16(byte[] data)
        {
            ushort crc = 0xFFFF;
            foreach (byte b in data)
            {
                crc ^= (ushort)(b << 8);
                for (int i = 0; i < 8; i++)
                {
                    if ((crc & 0x8000) != 0)
                        crc = (ushort)((crc << 1) ^ 0x1021);
                    else
                        crc <<= 1;
                }
            }
            //byte[] tempBytes = new byte[2];
            //ushort[] tempUshorts = new ushort[1] { crc };

            //Array.Copy(tempUshorts, 0, tempBytes, 0, 2); // 注意：这里的2是指复制的字节数，不是元素数
            //byte[] bytes = tempBytes; // 如果需要，可以创建一个新的数组并复制内容

            byte[] byteArray = new byte[2];
            byteArray[0] = (byte)(crc >> 8);  // 高8位
            byteArray[1] = (byte)(crc & 0xFF); // 低8位
            return byteArray;
        }

        /// <summary>
        /// crc16校验
        /// </summary>
        /// <param name="receive"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentException"></exception>
        internal static bool CheckCrc(byte[] receive)
        {
            int length = receive.Length;
            if (length < 2)
            {
                // 处理错误情况，例如抛出异常或记录错误日志
                throw new ArgumentException("The receive array must contain at least 2 elements.");
            }
            byte[] mainData = receive.Take(length - 2).ToArray();
            byte[] trailingBytes = receive.Skip(length - 2).ToArray(); // 这里不需要再次Take(2)，因为Skip已经定位到了正确的起始位置
            byte[] bytes = CalculateCRC16(mainData);
            if (bytes.Equals(trailingBytes))
            {
                return true;
            }
            return false;
        }

        /// <summary>
        /// bool[]转byte[]
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static byte[] GetByteArrayFromBoolArray(bool[] value)
        {
            int byteLength = (value.Length + 7) / 8;
            byte[] result = new byte[byteLength];
            for (int i = 0; i < value.Length; i++)
            {
                int byteIndex = i / 8;
                int bitIndex = i % 8;
                if (value[i])
                {
                    result[byteIndex] |= (byte)(1 << bitIndex);
                }
            }
            return result;
        }
    }
}
